package com.yx.fsysserver.user.controller;

import com.yx.fsysserver.common.constant.ConsHint;
import com.yx.fsysserver.common.CurrentUser;
import com.yx.fsysserver.common.constant.LoginConstant;
import com.yx.fsysserver.common.RandomImage;
import com.yx.fsysserver.common.result.JsonPageResult;
import com.yx.fsysserver.common.result.JsonResult;
import com.yx.fsysserver.user.domain.User;
import com.yx.fsysserver.user.service.UserService;
import com.yx.fsysserver.user.vo.PasswordVO;
import com.yx.fsysserver.user.vo.UserValidateCode;
import com.yx.lib.utils.StringHandle;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.crazycake.shiro.SerializeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Map;

/**
 * Created by liukailong on 2017/3/21.
 */
@RestController
@RequestMapping(value = "/user")
public class UserController {
    @Autowired
    private UserService userService;
    private final static Logger log = LoggerFactory.getLogger(UserController.class);
    /**
     * Created by lsn on 2018/02/06
     * 生成验证码
     * @param request
     * @param response
     * @throws ServletException,IOException
     */
    @RequestMapping(value = "/validateCode",method = RequestMethod.GET)
    public void validateCode(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setHeader("Cache-Control", "no-cache");
        String verifyCode = RandomImage.generateTextCode(RandomImage.TYPE_NUM_LOWER, 4, null);
        request.getSession().setAttribute("validateCode", verifyCode);
        response.setContentType("image/jpeg");
        BufferedImage bim = RandomImage.generateImageCode(verifyCode, 90, 30, 5, true, Color.WHITE, Color.BLUE, null);
        ImageIO.write(bim, "JPEG", response.getOutputStream());
    }

    /**
     * 登录
     * @return
     * @author liukailong
     * @since 2017-03-21
     * update by lsn on 2018/02/06
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public JsonResult signIn(@RequestBody UserValidateCode user, HttpServletRequest req) {
        log.debug(" to signIn");
        Assert.notNull(user.getAccount(), MessageFormat.format(ConsHint.ARG_VALIDATION_ERR, "账号"));

        //首先进行验证码验证
        Session session = SecurityUtils.getSubject().getSession();
        String code = (String) session.getAttribute("validateCode");
        String submitCode =user.getValidateCode();
        if (StringUtils.isEmpty(submitCode) || !submitCode.toLowerCase().equals(code)){
            req.setAttribute("LOGIN_ERROR_CODE", LoginConstant.LOGIN_ERROR_CODE_100000);
            req.setAttribute("LOGIN_ERROR_MESSAGE", LoginConstant.LOGIN_ERROR_MESSAGE_VALIDATECODE);
            return new JsonResult(false, "验证码输入错误，请重新输入！");
        }


        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken();
        token.setUsername(user.getAccount());
        token.setPassword(user.getPassword().toCharArray());
        try {
            subject.login(token);
        } catch (LockedAccountException lae) {
            token.clear();
            req.setAttribute("LOGIN_ERROR_CODE", LoginConstant.LOGIN_ERROR_CODE_100002);
            req.setAttribute("LOGIN_ERROR_MESSAGE", LoginConstant.LOGIN_ERROR_MESSAGE_SYSTEMERROR);
            return new JsonResult(false, "用户已经被锁定不能登录，请与管理员联系！");
        } catch (ExcessiveAttemptsException e) {
            token.clear();
            req.setAttribute("LOGIN_ERROR_CODE", LoginConstant.LOGIN_ERROR_CODE_100003);
            req.setAttribute("LOGIN_ERROR_MESSAGE","账号：" + user.getAccount() + LoginConstant.LOGIN_ERROR_MESSAGE_MAXERROR);
            return new JsonResult(false, "登录失败！用户名或密码错误!登录失败次数过多,锁定10分钟！");
        } catch (AuthenticationException e) {
            token.clear();
            req.setAttribute("LOGIN_ERROR_CODE", LoginConstant.LOGIN_ERROR_CODE_100001);
            req.setAttribute("LOGIN_ERROR_MESSAGE", LoginConstant.LOGIN_ERROR_MESSAGE_USERERROR);
            return new JsonResult(false, "登录失败！用户名或密码错误!");
            }

        Map<String,Object> mapUser = (Map<String,Object>) SerializeUtils.deserialize((byte[]) subject.getSession().getAttribute("user"));

        return new JsonResult(mapUser);
    }

    /**
     * 退出登录
     * @return
     * @author liukailong
     * @since 2017-03-07
     */
    @RequestMapping(value = "/logout",method = RequestMethod.POST)
    public JsonResult signOut() {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            subject.logout();
        }
        return new JsonResult(true, "退出成功");
    }

    /**
     * 权限异常处理
     * @param response
     * @return
     */
    @RequestMapping(value = "/403")
    public JsonResult sessionTimeOut(HttpServletResponse response) {
        response.setStatus(403);
        return new JsonResult(false,"权限异常，请重新登录");
    }

    /**
     *@Author liukailong
     *@Date 2017/3/7
     *@Description 修改密码
     *@params new 新密码 old 旧密码
     */
    @RequestMapping(value = "/password",method = RequestMethod.PUT)
    public JsonResult modifyPassword(@RequestBody PasswordVO passwordVO){
        Assert.notNull(passwordVO.getNewPassword(),MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"新密码"));
        Assert.notNull(passwordVO.getOldPassword(),MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"旧密码"));
        User user = userService.selectByPrimaryKey(CurrentUser.getUser().getId());

        //判断与旧密码是否相同
        if(!passwordVO.getOldPassword().equals( user.getPassword())){
            return new JsonResult(false,"旧密码错误，请重新输入");
        }

        //修改为新密码
        user.setPassword(passwordVO.getNewPassword());

        userService.updateByPrimaryKeySelective(user);

        return new JsonResult(true,ConsHint.UPDATE_SUCCESS);
    }

    /**
     *@Author cuihao
     *@Date 2017/6/26
     *@Description 列表
     *@params keyword：关键字
     *         pageNo:当前页码
     *         pageSize:每页条数
     */
    @RequestMapping(value = "/list",method = RequestMethod.GET)
    public JsonPageResult list(@RequestParam(name = "keyword",defaultValue = "", required = false) String name,
                               @RequestParam(value = "pageNo",defaultValue = "1", required = false) int pageNo,
                               @RequestParam(value = "pageSize",defaultValue = "10", required = false) int pageSize
    ){
        Assert.isTrue(0 < pageNo, MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,ConsHint.PAGE_NO));
        Assert.isTrue(0 < pageSize, MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,ConsHint.PAGE_SIZE));
        return userService.getList(pageNo,pageSize, StringHandle.escape4Like(name));
    }

    @GetMapping(value = "test")
    public JsonResult test(){
        userService.updateUser();
        return new JsonResult(true,"test");
    }
}
